/*
 * Copyright 2009 Colin Prinn
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

package net.recursv.motific.unittest;

import net.recursv.motific.unittest.impl.__TestSuiteIterator;
import net.recursv.motific.unittest.view.TestsCanvas;
import net.recursv.motific.utils.StringList;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Display;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import java.util.Vector;

/**
 * Created by: recursv
 * Date: 31/07/2009
 * Time: 5:14:58 PM
 *
 * @noinspection MissedExecutable
 */
abstract public class TestMidlet extends MIDlet {
    private TestResultPrinter _results;
    private TestSuiteIterator _iterator;
    private TestRunner _runner;
    private Canvas _canvas;

    public TestMidlet() {
        _iterator = createIterator(getTestSuitesToRun());
        _runner = createTestRunner();
        _canvas = createCanvas();

        _results = new TestResultPrinter(printStackTraces(), printPassedTests(), printFailedTests());
    }

    private TestsCanvas createCanvas() {
        return new TestsCanvas(this);
    }

    protected TestRunner createTestRunner() {
        return new TestRunner(this, _iterator);
    }

    protected TestSuiteIterator createIterator(StringList stringList) {
        if (stringList == null || stringList.size() == 0)
            return new __TestSuiteIterator();
        else
            return new FilteredTestSuiteIterator(stringList);
    }

    protected void destroyApp(boolean b) throws MIDletStateChangeException {
        _runner.cease();
    }

    protected void pauseApp() {
        throw new RuntimeException("Not implemented");
    }

    protected void startApp() throws MIDletStateChangeException {
        setCanvas(_canvas);
        _runner.start();
    }

    public final String getCurrentTestName() {
        return _runner.getTestName();
    }

    public final int getNumberOfTestCases() {
        return _iterator.countAllTestCases();
    }

    public final int getNumberOfCurrentTestCase() {
        return _runner.getTestNumber();
    }

    final void addResult(Throwable throwable, String suiteName, String methodName) {
        _results.addFailure(throwable, suiteName, methodName);
    }

    final void addResult(String suiteName, String methodName) {
        _results.addSuccess(suiteName, methodName);
    }

    public final boolean hasFailedTests() {
        return _results.hasFailedResults();
    }

    final void notifyCompletedAllTests() {
        _canvas.repaint();
    }

    final void notifyCeaseTesting() {
        _runner.cease();
    }

    final void notifyCompletedTestSuite() {
        _canvas.repaint();
    }

    final void notifyCompletedTestCase() {
        _canvas.repaint();
    }

    public final int getNumberOfSuccessfulTestCases() {
        return _results.countSuccessfulResults();
    }

    public final int getNumberOfFailedTestCases() {
        return _results.countFailedResults();
    }

    public final int getNumberOfTestSuites() {
        return _iterator.countTestSuites();
    }

    public Vector getFailedTestCases() {
        return _results.getFailedResults();
    }

    /**
     * Configuration method
     *
     * @return true to print exception stack traces
     */
    abstract protected boolean printStackTraces();

    /**
     * Configuration method.
     *
     * @return A list of test suite names to only execute certain test suites, null or an empty list to run all test suites.
     */
    abstract protected StringList getTestSuitesToRun();

    /**
     * Configuration method
     *
     * @return true to print passing test results
     */
    abstract protected boolean printPassedTests();

    /**
     * Configuration method
     *
     * @return true to print failing test results
     */
    abstract protected boolean printFailedTests();

    public final void setCanvas(Canvas canvas) {
        Display.getDisplay(this).setCurrent(canvas);
    }
}
